//实验一  处理机调度模拟
#include<stdio.h>
#include<stdlib.h>
enum state{ Wait = 1,Ready = 2 ,Run = 3, Finish = 4,Blcok = 5};
typedef struct process
{
    int pid;//PID
    int arriveTime;//到达时间
    int needRunTime;//需要运行时间
    int serverTime;//使用CPU时间
    enum state PState;
    struct process *next;
    int endTime;
}Process;
Process *ReadQue;//就绪队列头
Process *inputQue;//输入队列头
Process *FinsihQue; //完成队列头
Process *BlcokQueue; //完成队列头
Process *initProcess(){
    Process *p =(Process *) malloc(sizeof(Process));
    p->next = NULL;
    p->serverTime = 0;//设置服务时间为0
    return p;
}

Process *createProcess()
{
    Process *newProcess = initProcess();
    printf("\n正在创建进程.....\n");
    printf("\n请输入进程ID：");
    scanf("%d",&newProcess->pid);
    printf("\n请输入进程到达时间:");
    scanf("%d",&newProcess->arriveTime);
    printf("\n请输入进程需要运行的时间:");
    scanf("%d",&newProcess->needRunTime);
    newProcess->next = NULL;
    newProcess->PState = Wait;
    return newProcess;
}
Process *PushQueue(Process *head,Process *newProess){//入列
    Process *p = head;
    if(head->next == NULL){
        head->next = newProess;
    }
    else{
    while(p->next!=NULL)
    {
        p = p->next;
    }
        p->next = newProess;
    }
    return head;
}
Process *PopQueue(Process *head)//出列
{
    Process *first = head->next;
    head->next = first->next;
    first->next = NULL;
    return first;
}
void orderByArriveTime(Process *head){
    //冒泡排序
    Process *f, *p, *x, *y;
        f = NULL;
        if(head -> next == NULL || head -> next -> next == NULL)
        {
            return;
        }
        while(f != head->next->next)
        {
            for(p = head; p -> next -> next != f; p = p -> next)
            {
                if(p -> next -> arriveTime > p -> next -> next ->arriveTime)
                {
                    x = p -> next;
                    y = p -> next -> next;
                    p -> next = y;
                    x -> next = y -> next;
                    y -> next = x;
                }
            }
            f = p -> next;
        }
}

void printProcessInfo(Process *head)
{
    if(head->next!=NULL)
    {
    Process *p = head->next;
        printf("进程\t\t到达时间\t\t需要运行时间\t\t已使用CPU时间\t\t状态\t\t完成时间\n");
    while(p!=NULL)
    {
        printf("%d  \t\t ",p->pid);
        printf("%d  \t\t\t",p->arriveTime);
        printf("%d   \t\t\t",p->needRunTime);
        printf("%d    \t\t",p->serverTime);
        if(p->PState == 1){
            printf("Wai\n");
        }
        else if(p->PState == 2)
        {
            printf("Ready\n");
        }
        else if(p->PState == 3){
            printf("Run");
        }
        else if(p->PState == 5){
            printf("Block");
        }
        else{
            printf("Finish");
        }
        printf("\t\t%d",p->endTime);
        printf("\n");
        p = p->next;
    }
    }
}
int flag = 1;
void round_robin()
{
    printf("0时刻的输入队列为：\n");
    printProcessInfo(inputQue);
    int timeChip = 0;
    while(1)
    {
            if(inputQue->next==NULL&&ReadQue->next==NULL)//如果输入队列和就绪队列都为空，那么说明没有进程需要继续执行了，
            {
                break;
            }
            Process *p = NULL;
            if(BlcokQueue->next!=NULL)
            {
                 p = BlcokQueue->next;
                 p = PushQueue(ReadQue, p);
            }
        else{
            p = inputQue->next;
            if(p!=NULL && p->arriveTime <= timeChip)//输入队列的到达时间小于时间片的话，调入就绪队列
            {
                Process *first = PopQueue(inputQue);
                first->PState = Ready;//把状态改为就绪状态
                //                printf("状态:%d",first->PState);
                ReadQue = PushQueue(ReadQue, first);//调入就绪队列
            }
        }   
        
            if(ReadQue->next!=NULL)//开始运行
            {
                Process *RunningProcess = PopQueue(ReadQue);
                RunningProcess->PState = Run;
                RunningProcess->serverTime += 2;//单位时间
                RunningProcess->needRunTime  -= 2;
                printf("=======%d\n",flag);
                if(RunningProcess->pid == 2 && flag == 1)
                {
                    flag++;
                    RunningProcess->serverTime --;
                    RunningProcess->needRunTime ++;
                    RunningProcess->PState = 5;
                    timeChip--;
                    BlcokQueue = PushQueue(BlcokQueue, RunningProcess);
//                    ReadQue = PopQueue(ReadQue);
                }
                else if(RunningProcess->needRunTime ==0)//是否运行完毕
                 {
                     RunningProcess->PState = Finish;//标志完成
                     RunningProcess->endTime = timeChip;
                     FinsihQue = PushQueue(FinsihQue, RunningProcess);
                     RunningProcess = NULL;

                 }
                 else{//还未运行完毕
                     ReadQue = PushQueue(ReadQue,RunningProcess);
//                     printf("%d时刻就绪队列为：\n",timeChip);
//                     printProcessInfo(ReadQue);
                 }
            }
        printf("\n时刻:%d\n",timeChip);
        printf("%d时刻的就绪队列为：\n",timeChip);
        printProcessInfo(ReadQue);
        printf("%d时刻完成队列为：\n",timeChip);
        printProcessInfo(FinsihQue);
        timeChip += 2;
        }
    printf("当前时刻%d",timeChip);
}
//    process->needRunTime = process->needRunTime - timeChip;
//    process->serverTime += timeChip;
////    PopReadyQueue(head);
//    PushQueue(head, process);
//    printProcessInfo(head);
int main()
{
    int processNum;
    ReadQue = initProcess();//就绪队列头
    inputQue = initProcess();//输入队列头
    FinsihQue = initProcess();//完成队列头
    BlcokQueue = initProcess();//完成队列头
    printf("请输入你要创建进程的数量：");
    scanf("%d",&processNum);
    while(processNum-- > 0){
        Process *newProcess = createProcess();//新进程
        printf("%d",newProcess->arriveTime);
        inputQue = PushQueue(inputQue,newProcess);//经常入就绪队列
        printf("\n进程%d创建成功！\n",newProcess->pid);
        newProcess->endTime = -1;
    }
    orderByArriveTime(inputQue);//对在输入队列的进程按到达时间排序
    round_robin();
//    ReadQue = PushQueue(ReadQue, PopQueue(inputQue));
//    printProcessInfo(ReadQue);
//    printf("*******************");
//    printProcessInfo(inputQue);

}
